#ifndef __CLI_PARSE__DEBUG_H__
#define __CLI_PARSE__DEBUG_H__

#include "../../Epsilon/strings.h"

// Memory Profiling
#ifdef _DEBUG
#include <CRTDBG.H>
#endif

namespace cli_parse
{
  class Debug {
  public:
     Debug (bool print_to_stdout) {
       if (print_to_stdout) {
#ifdef _DEBUG
        _CrtSetReportHook (
#ifdef _UNICODE
        //_CrtSetReportHook (_CRT_RPT_HOOK_INSTALL,
#else
        //_CrtSetReportHook (_CRT_RPT_HOOK_INSTALL,
#endif
        &cli_parse::Debug::ReportHook);
#endif
       }
     };
    ~Debug (void) {
#ifdef _DEBUG
      _CrtSetReportHook (NULL);
        /*
#ifdef _UNICODE
       _CrtSetReportHookW2 (_CRT_RPT_HOOK_REMOVE,
#else
       _CrtSetReportHook2  (_CRT_RPT_HOOK_REMOVE,
#endif
       &cli_parse::Debug::ReportHook);
       */
#endif
    };

    void MemoryCheckpoint (const TCHAR* szDescription) {
#ifdef _DEBUG
      TCHAR szOut [1024];

      static int delta_TotalCount     = 0;
      static int delta_HighWaterCount = 0;

      //_CrtMemDumpAllObjectsSince (&memstate);
      _CrtMemCheckpoint          (&memstate);

      delta_TotalCount     = memstate.lTotalCount     - delta_TotalCount;
      delta_HighWaterCount = memstate.lHighWaterCount - delta_HighWaterCount;

      _sntprintf (szOut, 1023,
                    _T ("\n")
                    _T ("Memory Checkpoint (%s)\n")
                    _T (" >>  Current (change) = %d (%dk)\n")
                    _T (" >>> Peak    (change) = %d (%dk)\n"),
                      szDescription,
                        memstate.lTotalCount,
                          delta_TotalCount / 1024,
                            memstate.lHighWaterCount,
                              delta_HighWaterCount / 1024);

      _putts (szOut);
#endif
    }
    
    void DumpMemoryLeaks (void) {
#ifdef _DEBUG
      _CrtCheckMemory     ();
	    _CrtDumpMemoryLeaks ();
#endif
    }

    static int ReportHook (int type, char* szMessage, int* retVal) {
      fprintf (stdout, "%s\n", szMessage);
      fprintf (stderr, "%s\n", szMessage);
      //*retVal = 0;
      return 0;
    }

  private:
#ifdef _DEBUG
    _CrtMemState memstate;
#endif
  } extern *debug;
}

#endif /* __CLI_PARSE__DEBUG_H__ */
